package com.xs.ahoi.hcxs.ui.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller;
import com.xs.ahoi.hcxs.R;
import com.xs.ahoi.hcxs.animation.*;
import com.xs.ahoi.hcxs.model.vo.CharData;
import com.xs.ahoi.hcxs.service.BookFactory;
import com.xs.ahoi.hcxs.utils.Constants;
import com.xs.ahoi.hcxs.utils.ShortCutUtil;
import com.xs.ahoi.hcxs.utils.TextSelectUtil;
import com.xs.ahoi.hcxs.utils.ToastUtil;
import com.xs.ahoi.hcxs.utils.tts.TtsUtil;

/**
 * author: ahoi
 * date: 2018/6/20 20:47
 * description:
 */
public class BookContentView extends View {

    private BookFactory bookFactory;
    private Bitmap bitmapCurPage, bitmapNextPage;
    private AnimationProvider mAnimationProvider;
    private Scroller mScroller;
    // 翻页动画是否在执行
    private Boolean isAnimateRuning = false;

    // Touch事件监听
    private ContentTouchListener touchListener;
    // 屏幕尺寸
    private float screenWidth, screenHeight;
    // Touch时的新老坐标
    private float touchX, touchY, touchDownX, touchDownY, moveX, moveY, pressMoveX, pressMoveY;
    // 是否正在移动
    private boolean isMoving = false;
    // 判断是否向下翻页
    private boolean isNext = false;
    // 是否取消翻页
    private boolean isCancel = false;
    // 是否没下一页或者上一页
    private boolean noNext = false;
    // Touch时Y轴方向上的有效区域
    private float partUpY, partDownY;
    // 获取有效移动的最小距离，判断是否移动
    private int shortestMoveSlop;
    // 是否长按  长按是否执行
    private boolean isLongPress = false, isLongPressRun = false;
    // 长按坐标
    private float longPressX, longPressY;
    // 是否触摸落在滑块区域
    private boolean isClickInSlider = false;
    // 长按事件
    private Runnable mLongPressRunnable;
    // 长按选择工具类
    private TextSelectUtil selectUtil;
    // 阴影圆角图工具类
    private ShortCutUtil shortCutUtil;
    // 截图
    private Bitmap shortCut;


    // 构造函数
    public BookContentView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        bookFactory = BookFactory.getInstance();
        shortestMoveSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

        // 长按后执行
        mLongPressRunnable = () -> {
            if (isLongPress) {
                isLongPressRun = true;

                // 停止播放
                stopPlay(true);

                // 刷新页面
                postInvalidate();
            }
        };
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (isLongPressRun) {
            // 画长按
            selectUtil.setPageCharDatas(bookFactory.getPageCharDatas());
            if (isClickInSlider) {
                // 拖动滑块，绘制文字选中
                selectUtil.drawMove(pressMoveX, pressMoveY, canvas);

                // 绘制截图放大镜
                selectUtil.drawShortCut(canvas, shortCut, pressMoveX, pressMoveY);
            } else {
                // 画按下附近的文字
                if (!selectUtil.drawStatic(canvas, longPressX, longPressY)) {
                    finishLongPress();
                }
            }
        } else {
            // 画翻页动画
            if (mAnimationProvider != null) {
                if (isAnimateRuning) {
                    mAnimationProvider.drawMove(canvas);
                } else {
                    mAnimationProvider.drawStatic(canvas);
                }
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        // 如果菜单为显示状态，则直接隐藏
        if (touchListener.checkMenuShow()) {
            return false;
        }

        touchX = event.getX();
        touchY = event.getY();

        // 更新触摸点坐标
        mAnimationProvider.setTouchPoint(touchX, touchY);

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 如果按下时的Y小于100，则认为是意图滑下顶部状态栏
                if (touchY < 100) {
                    return false;
                }

                // 长按效果中，判断点击是否落在选中区域
                if (isLongPressRun) {
                    isClickInSlider = false;
                    // 如果落在区域外，则清除长按标记，并刷新页面
                    if (!selectUtil.isClickInSelectArea(touchX, touchY)) {
                        isLongPressRun = false;
                        // 隐藏操作弹框
                        touchListener.hideSelectedBtns();
                        touchListener.refreshPage();
                        // 停止可能会有的播放
                        TtsUtil.getInstance().stop();
                        return false;
                    } else {
                        isClickInSlider = true;
                    }

                    if (selectUtil.isClickInFirstSlider(touchX, touchY)) {
                        selectUtil.setClickInFirstSlider(true);
                    } else if (selectUtil.isClickInLastSlider(touchX, touchY)) {
                        selectUtil.setClickInLastSlider(true);
                    }
                } else {
                    // 长按参数，如果已经在长按中，就不重新赋值
                    longPressX = touchX;
                    longPressY = touchY;
                    pressMoveX = touchX;
                    pressMoveY = touchY;
                    isLongPress = false;

                    // 延时执行长按事件
                    removeCallbacks(mLongPressRunnable);
                    postDelayed(mLongPressRunnable, ViewConfiguration.getLongPressTimeout());
                }

                touchDownX = touchX;
                touchDownY = touchY;
                moveX = moveY = 0;
                isMoving = false;
                isNext = false;
                noNext = false;
                isAnimateRuning = false;

                // 设置按下时的坐标
                mAnimationProvider.setStartPoint(touchDownX, touchDownY);
                abortAnimation();

                break;
            case MotionEvent.ACTION_MOVE:

                // 获取有效移动的最小距离，判断是否移动
                if (!isMoving) {
                    isMoving = validMoveSlop();
                    // 如果移动了，就不是长按，没移动就标记为长按
                    isLongPress = !isMoving;
                }

                // 长按效果中，判断是否拖动首尾滑块
                if (isLongPressRun) {
                    if (isClickInSlider && validMoveSlop() && bookFactory.validDragMove(touchX, touchY)) {
                        // 获取当前view的截图
                        shortCut = getShortCut((int) touchX, (int) touchY);
                        // 隐藏操作弹框
                        touchListener.hideSelectedBtns();
                        postInvalidate();

                        pressMoveX = touchX;
                        pressMoveY = touchY;
                    }
                    return false;
                }

                if (isMoving) {
                    // 第一次触发时moveX == 0 && moveY ==0一定为true，目的为获取第一次移动时的意图，是next或prev
                    if (moveX == 0 && moveY == 0) {
                        if (touchX - touchDownX > 0) {
                            // 向右
                            isNext = false;
                        } else {
                            // 向左
                            isNext = true;
                        }
                        isCancel = false;
                        if (isNext) {
                            // 验证是否最后一页
                            if (bookFactory.isPageLast()) {
                                ToastUtil.show(R.string.last_page);
                                noNext = true;
                                return true;
                            }

                            mAnimationProvider.setDirection(AnimationProvider.Direction.next);

                            if (!isPlay()) {
                                doPageNext();
                            }
                        } else {
                            // 验证是否第一页
                            if (bookFactory.isPageFirst()) {
                                ToastUtil.show(R.string.first_page);
                                noNext = true;
                                return true;
                            }

                            mAnimationProvider.setDirection(AnimationProvider.Direction.pre);

                            if (!isPlay()) {
                                doPagePrev();
                            }
                        }
                    } else {
                        // 判断是否取消翻页
                        if (isNext) {
                            if (touchX - moveX > 0) {
                                isCancel = true;
                                mAnimationProvider.setCancel(true);
                            } else {
                                isCancel = false;
                                mAnimationProvider.setCancel(false);
                            }
                        } else {
                            if (touchX - moveX < 0) {
                                isCancel = true;
                                mAnimationProvider.setCancel(true);
                            } else {
                                isCancel = false;
                                mAnimationProvider.setCancel(false);
                            }
                        }
                    }

                    moveX = touchX;
                    moveY = touchY;

                    // 无翻页动画或者正在播放时，不执行移动动画
                    if (!isPlay()) {
                        isAnimateRuning = true;
                        this.postInvalidate();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                // 抬起后标记为不是长按
                isLongPress = false;
                shortCut = null;

                // 如果长按执行中，判断抬起时的坐标如果在选中区域外，就刷新页面，目的是隐藏放大镜
                if (isLongPressRun) {
                    // 弹出操作弹框
                    showSelectedTips();
                    postInvalidate();
                    return false;
                }

                // 正在播放中
                if (isPlay()) {
                    // 如果播放中，则滑动必需有效
                    if (!validMove()) {
                        return true;
                    }

                    if (isMoving) {
                        // 取消翻页
                        if (isCancel) {
                            return true;
                        }

                        if (isNext) {
                            doPageNext();
                        } else {
                            doPagePrev();
                        }

                        // 如果有下一页/上一页，就开始动画
                        if (!noNext) {
                            isAnimateRuning = true;
                            mAnimationProvider.startAnimation(mScroller);
                            postInvalidate();
                        }
                        return true;
                    }
                }

                // 没有移动，即为点击
                if (!isMoving) {
                    isCancel = false;
                    mAnimationProvider.setCancel(false);
                    if (touchY < partUpY) {
                        // 上一页
                        Boolean hasPre = doPagePrev();
                        mAnimationProvider.setDirection(AnimationProvider.Direction.pre);
                        // 重置按下时的坐标
                        if (!(mAnimationProvider instanceof SimulationAnimation)) {
                            mAnimationProvider.setStartPoint(0.01f, touchY);
                            mAnimationProvider.setTouchPoint(0.01f, touchY);
                        }
                        if (!hasPre) {
                            return true;
                        }
                    } else if (touchY > partDownY) {
                        // 下一页
                        Boolean hasNext = doPageNext();
                        mAnimationProvider.setDirection(AnimationProvider.Direction.next);
                        if (!hasNext) {
                            return true;
                        }
                    } else {
                        // 点击中间区域， 弹出菜单
                        touchListener.showMenu();
                        return true;
                    }
                }

                // 取消动画
                if (isCancel) {
                    touchListener.cancel();
                }

                // 如果有下一页/上一页，就开始动画
                if (!noNext) {
                    isAnimateRuning = true;
                    mAnimationProvider.startAnimation(mScroller);
                    this.postInvalidate();
                }
                break;
            default:
                break;
        }
        return true;
    }

    @Override
    public void computeScroll() {
        if (mScroller != null && mScroller.computeScrollOffset()) {
            float x = mScroller.getCurrX();
            float y = mScroller.getCurrY();
            mAnimationProvider.setTouchPoint(x, y);
            if (mScroller.getFinalX() == x && mScroller.getFinalY() == y) {
                isAnimateRuning = false;
            }
            postInvalidate();
        }
        super.computeScroll();
    }

    // 停止动画
    public void abortAnimation() {
        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
            mAnimationProvider.setTouchPoint(mScroller.getFinalX(), mScroller.getFinalY());
            postInvalidate();
        }
    }

    // 设置翻页动画
    public void setPageStyle(int pageStyle) {
        switch (pageStyle) {
            case Constants.PAGE_STYLE_SIMULATION:
                mAnimationProvider = new SimulationAnimation(bitmapCurPage, bitmapNextPage, (int) screenWidth, (int) screenHeight);
                break;
            case Constants.PAGE_STYLE_SLIDE:
                mAnimationProvider = new SlideAnimation(bitmapCurPage, bitmapNextPage, (int) screenWidth, (int) screenHeight);
                break;
            case Constants.PAGE_STYLE_COVER:
                mAnimationProvider = new CoverAnimation(bitmapCurPage, bitmapNextPage, (int) screenWidth, (int) screenHeight);
                break;
            case Constants.PAGE_STYLE_NONE:
                mAnimationProvider = new NoneAnimation(bitmapCurPage, bitmapNextPage, (int) screenWidth, (int) screenHeight);
                break;
            default:
                mAnimationProvider = new CoverAnimation(bitmapCurPage, bitmapNextPage, (int) screenWidth, (int) screenHeight);
        }
    }


    //**********************************************************
    //********************get set 方法**************************
    //**********************************************************


    // 获取当前view的截图
    private Bitmap getShortCut(int touchX, int touchY) {
        Bitmap cache = getDrawingCache();
        int x = touchX - Constants.SHORT_CUT_WIDTH / 2;
        int y = touchY - Constants.SHORT_CUT_HEIGHT / 2;
        x = x < 0 ? 0 : x;
        y = y < 0 ? 0 : y;
        if (x + Constants.SHORT_CUT_WIDTH > screenWidth) {
            x = (int) (screenWidth - Constants.SHORT_CUT_WIDTH);
        }
        if (y + Constants.SHORT_CUT_HEIGHT > screenHeight) {
            y = (int) (screenHeight - Constants.SHORT_CUT_HEIGHT);
        }

        Bitmap bitmap = Bitmap.createBitmap(cache, x, y, Constants.SHORT_CUT_WIDTH, Constants.SHORT_CUT_HEIGHT);
        return shortCutUtil.getRoundAndShadow(bitmap, 20);
    }

    // 如果是无动画或正在播放，就不显示移动动画
    private boolean isPlay() {
        return mAnimationProvider instanceof NoneAnimation || touchListener.isPlaying();
    }

    // 取消长按标记
    public void finishLongPress() {
        isLongPress = false;
        isLongPressRun = false;
        isClickInSlider = false;
    }

    // 弹出操作弹框
    private void showSelectedTips() {
        CharData firstChar = selectUtil.getFirstChar();
        CharData lastChar = selectUtil.getLastChar();
        if (firstChar == null || lastChar == null) {
            return;
        }

        float btnsHeight = getResources().getDimension(R.dimen.selected_btns_height);
        float margin = getResources().getDimension(R.dimen.selected_btns_margin) + Constants.SELECT_SLIDER_RADIUS * 2;
        float positionY = firstChar.getTop() - btnsHeight - margin;
        if (positionY < 0) {
            positionY = lastChar.getBottom() + margin;
            if (positionY + btnsHeight > screenHeight) {
                positionY = (screenHeight - btnsHeight) / 2;
            }
        }
        touchListener.showSelectedBtns(positionY);
    }

    // 有效的移动操作 只有当x方向移动的差值大于y方向移动的差值，才执行翻页
    private Boolean validMove() {
        return Math.abs(touchX - touchDownX) >= Math.abs(touchY - touchDownY);
    }

    // 移动距离是否有效
    private boolean validMoveSlop() {
        return Math.abs(touchDownX - touchX) > shortestMoveSlop || Math.abs(touchDownY - touchY) > shortestMoveSlop;
    }

    // 设置bitmap
    public void setBitmap(Bitmap bitmapCurPage, Bitmap bitmapNextPage) {
        this.bitmapCurPage = bitmapCurPage;
        this.bitmapNextPage = bitmapNextPage;
    }

    // 设置屏幕尺寸
    public void setSize(float screenWidth, float screenHeight) {
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;
    }

    // 初始化
    public void init() {
        // 计算Y轴方向有效区域（上下浮动30 %）
        partUpY = screenHeight / 2 * 0.7f;
        partDownY = screenHeight / 2 * 1.3f;

        mScroller = new Scroller(getContext(), new LinearInterpolator());

        finishLongPress();

        // 初始化文字选中工具类
        selectUtil = new TextSelectUtil(bitmapCurPage, bitmapNextPage, screenWidth, screenHeight);
        shortCutUtil = new ShortCutUtil();

        // 设置开启缓存
        setDrawingCacheEnabled(true);
        buildDrawingCache();
    }

    // 是否正在播放
    public boolean isPlaying() {
        return touchListener.isPlaying();
    }

    // 停止播放
    public void stopPlay(boolean isActStop) {
        if (touchListener != null) {
            touchListener.stopPlay(isActStop);
        }
    }

    // 停止倒计时
    public void cancelTimer() {
        if (touchListener != null) {
            touchListener.cancelTimer();
        }
    }

    // 开始播放
    public Boolean startPlay() {
        if (touchListener != null) {
            return touchListener.startPlay();
        }
        return false;
    }

    // 是否长按中
    public boolean isLongPressRun() {
        return isLongPressRun;
    }

    // 下一页
    public Boolean doPageNext(Integer position) {
        return touchListener.nextPage(position);
    }

    public Boolean doPageNext() {
        return doPageNext(null);
    }

    // 上一页
    public Boolean doPagePrev() {
        return touchListener.prevPage();
    }

    // 设置TouchListener
    public void setTouchListener(ContentTouchListener touchListener) {
        this.touchListener = touchListener;
    }

    // 监听触摸接口，传递给activity执行实现
    public interface ContentTouchListener {

        // 上一页
        Boolean prevPage();

        // 下一页
        Boolean nextPage(Integer position);

        // 刷新当前页
        void refreshPage();

        // 是否正在播放
        Boolean isPlaying();

        // 点击中心，弹出设置菜单
        void showMenu();

        // 取消翻页
        void cancel();

        // 点击前判断是否打开了设置菜单，如果打开了，就关闭，然后返回true
        Boolean checkMenuShow();

        // 停止播放
        void stopPlay(boolean isActStop);

        // 停止倒计时
        void cancelTimer();

        // 开始播放
        Boolean startPlay();

        // 选中后显示操作弹框
        void showSelectedBtns(float positionY);

        // 取消选中后隐藏操作弹框
        void hideSelectedBtns();

    }

}
